package cgpoly_go

//#cgo LDFLAGS: -Wl,--copy-dt-needed-entries -L${SRCDIR} -lcgpoly -lCGAL -lmpfr -lgmp
//#include <stdlib.h>
//#include "cgpoly.h"
import "C"
import "unsafe"
import "fmt"
import "os"

type Point []float64
type Bound []Point
type Poly []Bound
type PolyArea []Poly

func (pa PolyArea) SetCGPoly (id int) {
	C.PASetNewPA (C.int(id))
	for _, p := range pa {
		C.PASetNewPoly (C.char(1))
		for _, b := range p {
			C.PASetNewBound ()
			for _, point := range b {
				C.PASetNewPoint (C.double(point[0]), C.double(point[1]))
			}
			C.PASetEndBound()
		}
		C.PASetEndPoly()
	}
	C.PASetEndPA ()
}

func GetCGPoly (id int) PolyArea {
	npoly := int(C.PAGetNPoly(C.int(id)))
	pa := make(PolyArea, npoly)
	for i := 0; i < npoly; i ++ {
		pa[i] = make (Poly, C.PAGetNHole (C.int(id), C.int(i)) + 1)
		np := int(C.PAGetOutterBoundNPoint (C.int(id), C.int(i)))
		pa[i][0] = make (Bound, np)
		for j := 0; j < np; j ++ {
			pa[i][0][j] = make(Point, 2)
			pa[i][0][j][0] = float64(C.PAGetOBX (C.int(id), C.int(i), C.int(j)))
			pa[i][0][j][1] = float64(C.PAGetOBY (C.int(id), C.int(i), C.int(j)))
		}
		k := 1
		for C.PAIterateHoleBegin (C.int(id), C.int(i)) ; C.PAIterateHoleIsContinue() != 0; C.PAIterateHoleNext () {
			np = int (C.PAGetHoleNPoint())
			pa[i][k] = make (Bound, np)
			for j := 0; j < np; j ++ {
				pa[i][k][j] = make(Point, 2)
				pa[i][k][j][0] = float64(C.PAGetHoleX (C.int(j)))
				pa[i][k][j][1] = float64(C.PAGetHoleY (C.int(j)))
			}
			k ++
		}
	}

	return pa
}

func CGPolyDiff (pa1, pa2, res int) {
      C.PADiff (C.int(pa1), C.int(pa2), C.int(res))
}

func CGPolyUnion (pa1, pa2, res int) {
      C.PAUnion (C.int(pa1), C.int(pa2), C.int(res))
}

func CGPolyInter (pa1, pa2, res int) {
      C.PAInter (C.int(pa1), C.int(pa2), C.int(res))
}

func PolyAreaCut (pa1 PolyArea, pa2 PolyArea) (diff PolyArea, inter PolyArea) {

	pa1.SetCGPoly (0)
	pa2.SetCGPoly (1)

      CGPolyDiff  (0, 1, 2)
      CGPolyInter (0, 1, 3)
	
	diff = GetCGPoly (2)
	inter = GetCGPoly (3)

	return 
}

func (pa PolyArea) Print (fout_name string) {
	cstr := C.CString (fout_name)
	pa.SetCGPoly (4)

	C.PAPrint (cstr, C.int(4))
	C.free (unsafe.Pointer(cstr))
}

func (a PolyArea) Draw (fout * os.File) {
      for _, poly := range a {
            for _, bound := range poly {
                  for i := 0; i < len(bound); i ++ {
                        ii := (i + 1) % len(bound)
                        fmt.Fprintf (fout, "draw ((%12.4f, %12.4f) -- (%12.4f, %12.4f));\n", 
                        bound[i][0], bound[i][1], bound[ii][0], bound[ii][1]) 
                  }
            }
      }
}

